package com.cango.student;

import java.util.LinkedList;

/**
 * 滑动窗口限流
 */
public class LocalRateLimit {
    //服务访问次数，可以放在Redis中，实现分布式系统的访问计数
    Long counter = 0L;
    //使用LinkedList来记录滑动窗口的10个格子。
    LinkedList<Long> ll = new LinkedList<Long>();

    /**
     * 计数器是最简单粗暴的算法。
     * 比如某个服务最多只能每秒钟处理100个请求。我们可以设置一个1秒钟的滑动窗口，窗口中有10个格子，每个格子100毫秒，每100毫秒移动一次，每次移动都需要记录当前服务请求的次数。
     * 内存中需要保存10次的次数。可以用数据结构LinkedList来实现。格子每次移动的时候判断一次，当前访问次数和LinkedList中最后一个相差是否超过100，如果超过就需要限流了。
     */
    private void doCheck() {
        while (true) {
            ll.addLast(counter);

            if (ll.size() > 10) {
                ll.removeFirst();
            }

            //比较最后一个和第一个，两者相差一秒
            if ((ll.peekLast() - ll.peekFirst()) > 100) {
                // 限流操作
            }
            try {
                Thread.sleep(100);
            } catch (InterruptedException ex) {

            }

        }
    }

    public static void main(String[] args) {
        LocalRateLimit counter = new LocalRateLimit();

        counter.doCheck();
    }
}
